from cProfile import label
import numpy as np
import os
from apk_process import process_apk, process_apk_lib
import pickle
import scipy.io as sio
import scipy.sparse as sparse
import time


# apk_path_list = ["./sample_apk/000db93ae6b67e6303e5b5b4839df016.apk", 
#             "./sample_apk/000f3a904966dcffed17a965c183ba70.apk",
#             "./sample_apk/000316cad2ed6477e73d839f60115e5f.apk"]
apk_path_list = sio.loadmat("./output_dir/apk_list_and_label.mat")
apk_path_list = apk_path_list["apk_path_list"].tolist()
apk_path_list = [x.split()[0] for x in apk_path_list]

lib_dict = {}  # library


'''
class Myapk():
    def __init__(self, permission, apk_class, library, interface, methods):
        self.permission = permission
        self.apk_class = apk_class
        self.library = library
        self.interface = interface
        self.methods = methods
        self.per_vector = []
        self.cla_vector = []
        self.lib_vector = []
        self.int_vector = []
        self.met_vector = [] 
'''

# per_feature = []    # permission
# cla_feature = []    # class
# lib_feature = []    # library
# int_feature = []    # interface
# met_feature = []    # method

# Collect all features
apk_list = []
count = 0
for apk_idx in range(len(apk_path_list)):
    apk = process_apk_lib(apk_path_list[apk_idx], lib_dict)   
    apk_list.append(apk)
    count += 1
    print(apk_path_list[apk_idx] + " Done! " + str(count))
    # if count == 100:
    #     break


# judge 0 or 1 
def fun(feature, self_feature_list):
    if feature in self_feature_list:
        return 1
    else:
        return 0 

# Construct vector for every APK
apk_feature_list_lib = []
count = 0
for apk in apk_list:
    #apk_feature = []
    ''' This part optimized
    apk.per_vector = np.array([fun(x, apk.permission) for x in list(per_dict.values())])
    apk.cla_vector = np.array([fun(x, apk.apk_class) for x in list(cla_dict.values())])
    apk.lib_vector = np.array([fun(x, apk.library) for x in list(lib_dict.values())])
    apk.int_vector = np.array([fun(x, apk.interface) for x in list(int_dict.values())])
    apk.met_vector = np.array([fun(x, apk.methods) for x in list(met_dict.values())])
    '''
        
    apk.lib_vector = [0] * len(lib_dict.values())
    for item in apk.library:
        apk.lib_vector[item] = 1

    apk.lib_vector = np.array(apk.lib_vector, dtype=bool) 
    apk_feature_list_lib.append(apk.lib_vector)
    
    count += 1
    print(str(count) + "apk vector build")

apk_feature_list_lib = np.array(apk_feature_list_lib, dtype=bool)

apk_feature_list_lib = sparse.csr_matrix(apk_feature_list_lib)


    
try:
    sio.savemat("./output_dir/apk_feature_list_lib.mat", 
                mdict={"apk_feature_list_lib": apk_feature_list_lib})
    print("apk_feature_list_lib.mat save done!")
except Exception as e:
    print("apk_feature_list_lib.mat save faild")
    print(e)
    

    
try:
    with open("./output_dir/lib_dict.txt", 'w') as f:
        for i in lib_dict.items():
            f.write(str(i)+'\n')
    print("lib_dict save done")
except Exception as e:
    print("lib_dict save failed")
    print(e)
        


# Construct graph
library_graph = np.zeros((len(apk_list), len(apk_list)), dtype=bool)

count = 0
time_point_4 = time.time()
for i in range(len(apk_list)):
    for j in range(i, len(apk_list)):
        multi_result = np.multiply(apk_list[i].lib_vector, apk_list[j].lib_vector)
        if (1 in multi_result) or i==j:
            library_graph[i][j] = 1
    count += 1
    print(str(count) + "apk graph build")

# Get the symmetric matrix. Bool array, no need to subtract np.eye(length)
library_graph = library_graph + library_graph.T


library_graph = sparse.csr_matrix(library_graph | np.eye(len(apk_list), dtype=bool))


sio.savemat("./output_dir/apk_graph_lib.mat",mdict={
                                 "library_graph":library_graph
                                 }, long_field_names=True)
print("Graph save done!")

